﻿using System;
using System.Collections.Generic;
using System.Text;
using Pixysoft.Framework.Logs.Core;

namespace Pixysoft.Framework.Logs.Controller
{
    class LogNonStructureSerializeController
    {
        private static volatile LogNonStructureSerializeController instance;

        private static object syncRoot = new Object();

        public static LogNonStructureSerializeController Instance
        {
            get
            {
                if (instance == null)
                {
                    lock (syncRoot)
                    {
                        instance = new LogNonStructureSerializeController();
                    }
                }

                return instance;

            }
        }


        public string Serialize(ILogRecord record)
        {
            if (record == null)
                return null;

            StringBuilder builder = new StringBuilder();

            Serialize(record, builder);

            return builder.ToString();
        }

        private void Serialize(ILogRecord record, StringBuilder builder)
        {
            //2010-02-09 bug!!! 索引从0开始

            builder.AppendLine(string.Format("{0}\t{1}\t{2}\t{3}", record.RawDate, record.Level, record.Ip, record.Id));
            builder.AppendLine(record.Text);

            if (record.Frames.Count == 0)
                return;

            foreach (ILogFrame frame in record.Frames)
            {
                builder.AppendLine(string.Format("{0}:{1}.{2} {3}{4} line:{5} column:{6}",
                    frame.Dll, frame.Class, frame.Method,
                    frame.Path, frame.File,
                    frame.Line, frame.Column));
            }
        }


        public string Serialize(ILogDocument doc)
        {
            if (doc == null)
                return null;

            StringBuilder builder = new StringBuilder();

            Serialize(doc, builder);

            return builder.ToString();
        }

        private void Serialize(ILogDocument doc, StringBuilder builder)
        {
            builder.AppendLine("SUMMARY: " + Summary(doc).RawSerialize());
            builder.AppendLine();

            foreach (ILogRecord record in doc.Records)
            {
                Serialize(record, builder);
                builder.AppendLine();
            }

            builder.AppendLine();
        }


        public string Serialize(ILogReport report)
        {
            if (report == null)
                return null;

            StringBuilder builder = new StringBuilder();

            Serialize(report, builder);

            return builder.ToString();
        }

        private void Serialize(ILogReport report, StringBuilder builder)
        {
            builder.AppendLine(string.Format("{0} - {1}", report.TimeFrom.ToString(StringHelper.default_log_dateformat),
                report.TimeTo.ToString(StringHelper.default_log_dateformat)));
            builder.AppendLine();


            if (report.Document != null && report.Document.Records.Count > 0)
            {
                Serialize(report.Document, builder);
            }

            if (report.FrameDocuments != null && report.FrameDocuments.Length > 0)
            {
                foreach (ILogDocument doc in report.FrameDocuments)
                {
                    Serialize(doc, builder);
                }
            }
        }


        public string Serialize(ILogDocumentSummary summary)
        {
            if (summary == null)
                return null;

            StringBuilder builder = new StringBuilder();

            Serialize(summary, builder);

            return builder.ToString();
        }

        private void Serialize(ILogDocumentSummary summary, StringBuilder builder)
        {
            builder.AppendLine(string.Format("FATAL:{0} ERROR:{1} WARN:{2} INFO:{3} DEBUG:{4}",
                summary.CountOfFatal,
                summary.CountOfError,
                summary.CountOfWarn,
                summary.CountOfInfo,
                summary.CountOfDebug));
        }


        private ILogDocumentSummary Summary(ILogDocument doc)
        {
            LogDocumentSummary summary = new LogDocumentSummary();

            if (doc == null)
                return summary;

            summary.RecordCount = doc.Records.Count;

            foreach (ILogRecord record in doc.Records)
            {
                if (summary.TimeFrom > record.Date)
                    summary.TimeFrom = record.Date;

                if (summary.TimeTo < record.Date)
                    summary.TimeTo = record.Date;

                switch (record.Level)
                {
                    case LogLevel.DEBUG:
                        summary.CountOfDebug++;
                        break;
                    case LogLevel.ERROR:
                        summary.CountOfError++;
                        break;
                    case LogLevel.FATAL:
                        summary.CountOfFatal++;
                        break;
                    case LogLevel.INFO:
                        summary.CountOfInfo++;
                        break;
                    case LogLevel.WARN:
                        summary.CountOfWarn++;
                        break;
                }
            }

            return summary;
        }
    }
}
